home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 002 / emacssrc.arc / RANDOM.C < prev    next >
Encoding:
C/C++ Source or Header  |  1987-02-05  |  24.4 KB  |  916 lines

  1. /*
  2.  * This file contains the command processing functions for a number of random
  3.  * commands. There is no functional grouping here, for sure.
  4.  */
  5.  
  6. #include        <stdio.h>
  7. #include    "estruct.h"
  8. #include        "edef.h"
  9.  
  10. #if    MEGAMAX & ST520
  11. overlay "random"
  12.  
  13. extern int STncolors;
  14. #endif
  15.  
  16. int     tabsize;                        /* Tab size (0: use real tabs)  */
  17.  
  18. /*
  19.  * Set fill column to n.
  20.  */
  21. setfillcol(f, n)
  22. {
  23.         fillcol = n;
  24.     mlwrite("[Fill column is %d]",n);
  25.         return(TRUE);
  26. }
  27.  
  28. /*
  29.  * Display the current position of the cursor, in origin 1 X-Y coordinates,
  30.  * the character that is under the cursor (in hex), and the fraction of the
  31.  * text that is before the cursor. The displayed column is not the current
  32.  * column, but the column that would be used on an infinite width display.
  33.  * Normally this is bound to "C-X =".
  34.  */
  35. showcpos(f, n)
  36. {
  37.         register LINE   *lp;        /* current line */
  38.         register long   numchars;    /* # of chars in file */
  39.         register int    numlines;    /* # of lines in file */
  40.         register long   predchars;    /* # chars preceding point */
  41.         register int    predlines;    /* # lines preceding point */
  42.         register int    curchar;    /* character under cursor */
  43.         int ratio;
  44.         int col;
  45.     int savepos;            /* temp save for current offset */
  46.     int ecol;            /* column pos/end of current line */
  47.  
  48.     /* starting at the beginning of the buffer */
  49.         lp = lforw(curbp->b_linep);
  50.  
  51.     /* start counting chars and lines */
  52.         numchars = 0;
  53.         numlines = 0;
  54.         while (lp != curbp->b_linep) {
  55.         /* if we are on the current line, record it */
  56.         if (lp == curwp->w_dotp) {
  57.             predlines = numlines;
  58.             predchars = numchars + curwp->w_doto;
  59.             if ((curwp->w_doto) == llength(lp))
  60.                 curchar = '\n';
  61.             else
  62.                 curchar = lgetc(lp, curwp->w_doto);
  63.         }
  64.         /* on to the next line */
  65.         ++numlines;
  66.         numchars += llength(lp) + 1;
  67.         lp = lforw(lp);
  68.         }
  69.  
  70.     /* if at end of file, record it */
  71.     if (curwp->w_dotp == curbp->b_linep) {
  72.         predlines = numlines;
  73.         predchars = numchars;
  74.     }
  75.  
  76.     /* Get real column and end-of-line column. */
  77.     col = getccol(FALSE);
  78.     savepos = curwp->w_doto;
  79.     curwp->w_doto = llength(curwp->w_dotp);
  80.     ecol = getccol(FALSE);
  81.     curwp->w_doto = savepos;
  82.  
  83.         ratio = 0;              /* Ratio before dot. */
  84.         if (numchars != 0)
  85.                 ratio = (100L*predchars) / numchars;
  86.  
  87.     /* summarize and report the info */
  88.     mlwrite("Line %d/%d Col %d/%d Char %D/%D (%d%%) char = 0x%x",
  89.         predlines+1, numlines+1, col, ecol,
  90.         predchars, numchars, ratio, curchar);
  91.         return (TRUE);
  92. }
  93.  
  94. getcline()    /* get the current line number */
  95.  
  96. {
  97.         register LINE   *lp;        /* current line */
  98.         register int    numlines;    /* # of lines before point */
  99.  
  100.     /* starting at the beginning of the buffer */
  101.         lp = lforw(curbp->b_linep);
  102.  
  103.     /* start counting lines */
  104.         numlines = 0;
  105.         while (lp != curbp->b_linep) {
  106.         /* if we are on the current line, record it */
  107.         if (lp == curwp->w_dotp)
  108.             break;
  109.         ++numlines;
  110.         lp = lforw(lp);
  111.         }
  112.  
  113.     /* and return the resulting count */
  114.     return(numlines + 1);
  115. }
  116.  
  117. /*
  118.  * Return current column.  Stop at first non-blank given TRUE argument.
  119.  */
  120. getccol(bflg)
  121. int bflg;
  122. {
  123.         register int c, i, col;
  124.         col = 0;
  125.         for (i=0; i<curwp->w_doto; ++i) {
  126.                 c = lgetc(curwp->w_dotp, i);
  127.                 if (c!=' ' && c!='\t' && bflg)
  128.                         break;
  129.                 if (c == '\t')
  130.                         col |= 0x07;
  131.                 else if (c<0x20 || c==0x7F)
  132.                         ++col;
  133.                 ++col;
  134.         }
  135.         return(col);
  136. }
  137.  
  138. /*
  139.  * Set current column.
  140.  */
  141. setccol(pos)
  142.  
  143. int pos;    /* position to set cursor */
  144.  
  145. {
  146.         register int c;        /* character being scanned */
  147.     register int i;        /* index into current line */
  148.     register int col;    /* current cursor column   */
  149.     register int llen;    /* length of line in bytes */
  150.  
  151.     col = 0;
  152.     llen = llength(curwp->w_dotp);
  153.  
  154.     /* scan the line until we are at or past the target column */
  155.     for (i = 0; i < llen; ++i) {
  156.         /* upon reaching the target, drop out */
  157.         if (col >= pos)
  158.             break;
  159.  
  160.         /* advance one character */
  161.                 c = lgetc(curwp->w_dotp, i);
  162.                 if (c == '\t')
  163.                         col |= 0x07;
  164.                 else if (c<0x20 || c==0x7F)
  165.                         ++col;
  166.                 ++col;
  167.         }
  168.     /* if not long enough... */
  169.     if (col < pos)
  170.         return(FALSE);
  171.  
  172.     /* otherwise...set us at the new position */
  173.     curwp->w_doto = i;
  174.     return(TRUE);
  175. }
  176.  
  177. /*
  178.  * Twiddle the two characters on either side of dot. If dot is at the end of
  179.  * the line twiddle the two characters before it. Return with an error if dot
  180.  * is at the beginning of line; it seems to be a bit pointless to make this
  181.  * work. This fixes up a very common typo with a single stroke. Normally bound
  182.  * to "C-T". This always works within a line, so "WFEDIT" is good enough.
  183.  */
  184. twiddle(f, n)
  185. {
  186.         register LINE   *dotp;
  187.         register int    doto;
  188.         register int    cl;
  189.         register int    cr;
  190.  
  191.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  192.         return(rdonly());    /* we are in read only mode    */
  193.         dotp = curwp->w_dotp;
  194.         doto = curwp->w_doto;
  195.         if (doto==llength(dotp) && --doto<0)
  196.                 return (FALSE);
  197.         cr = lgetc(dotp, doto);
  198.         if (--doto < 0)
  199.                 return (FALSE);
  200.         cl = lgetc(dotp, doto);
  201.         lputc(dotp, doto+0, cr);
  202.         lputc(dotp, doto+1, cl);
  203.         lchange(WFEDIT);
  204.         return (TRUE);
  205. }
  206.  
  207. /*
  208.  * Quote the next character, and insert it into the buffer. All the characters
  209.  * are taken literally, with the exception of the newline, which always has
  210.  * its line splitting meaning. The character is always read, even if it is
  211.  * inserted 0 times, for regularity. Bound to "C-Q"
  212.  */
  213. quote(f, n)
  214. {
  215.         register int    s;
  216.         register int    c;
  217.  
  218.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  219.         return(rdonly());    /* we are in read only mode    */
  220.         c = tgetc();
  221.         if (n < 0)
  222.                 return (FALSE);
  223.         if (n == 0)
  224.                 return (TRUE);
  225.         if (c == '\n') {
  226.                 do {
  227.                         s = lnewline();
  228.                 } while (s==TRUE && --n);
  229.                 return (s);
  230.         }
  231.         return (linsert(n, c));
  232. }
  233.  
  234. /*
  235.  * Set tab size if given non-default argument (n <> 1).  Otherwise, insert a
  236.  * tab into file.  If given argument, n, of zero, change to true tabs.
  237.  * If n > 1, simulate tab stop every n-characters using spaces. This has to be
  238.  * done in this slightly funny way because the tab (in ASCII) has been turned
  239.  * into "C-I" (in 10 bit code) already. Bound to "C-I".
  240.  */
  241. tab(f, n)
  242. {
  243.         if (n < 0)
  244.                 return (FALSE);
  245.         if (n == 0 || n > 1) {
  246.                 tabsize = n;
  247.                 return(TRUE);
  248.         }
  249.         if (! tabsize)
  250.                 return(linsert(1, '\t'));
  251.         return(linsert(tabsize - (getccol(FALSE) % tabsize), ' '));
  252. }
  253.  
  254. /*
  255.  * Open up some blank space. The basic plan is to insert a bunch of newlines,
  256.  * and then back up over them. Everything is done by the subcommand
  257.  * procerssors. They even handle the looping. Normally this is bound to "C-O".
  258.  */
  259. openline(f, n)
  260. {
  261.         register int    i;
  262.         register int    s;
  263.  
  264.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  265.         return(rdonly());    /* we are in read only mode    */
  266.         if (n < 0)
  267.  
  268.                 return (FALSE);
  269.         if (n == 0)
  270.                 return (TRUE);
  271.         i = n;                                  /* Insert newlines.     */
  272.         do {
  273.                 s = lnewline();
  274.         } while (s==TRUE && --i);
  275.         if (s == TRUE)                          /* Then back up overtop */
  276.                 s = backchar(f, n);             /* of them all.         */
  277.         return (s);
  278. }
  279.  
  280. /*
  281.  * Insert a newline. Bound to "C-M". If we are in CMODE, do automatic
  282.  * indentation as specified.
  283.  */
  284. newline(f, n)
  285. {
  286.     register int    s;
  287.  
  288.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  289.         return(rdonly());    /* we are in read only mode    */
  290.     if (n < 0)
  291.         return (FALSE);
  292.  
  293.     /* if we are in C mode and this is a default <NL> */
  294.     if (n == 1 && (curbp->b_mode & MDCMOD) &&
  295.         curwp->w_dotp != curbp->b_linep)
  296.         return(cinsert());
  297.  
  298.         /*
  299.          * If a newline was typed, fill column is defined, the argument is non-
  300.          * negative, wrap mode is enabled, and we are now past fill column,
  301.      * and we are not read-only, perform word wrap.
  302.          */
  303.         if ((curwp->w_bufp->b_mode & MDWRAP) && fillcol > 0 &&
  304.         getccol(FALSE) > fillcol &&
  305.         (curwp->w_bufp->b_mode & MDVIEW) == FALSE)
  306.         execute(META|SPEC|'W', FALSE, 1);
  307.  
  308.     /* insert some lines */
  309.     while (n--) {
  310.         if ((s=lnewline()) != TRUE)
  311.             return (s);
  312.     }
  313.     return (TRUE);
  314. }
  315.  
  316. cinsert()    /* insert a newline and indentation for C */
  317.  
  318. {
  319.     register char *cptr;    /* string pointer into text to copy */
  320.     register int tptr;    /* index to scan into line */
  321.     register int bracef;    /* was there a brace at the end of line? */
  322.     register int i;
  323.     char ichar[NSTRING];    /* buffer to hold indent of last line */
  324.  
  325.     /* grab a pointer to text to copy indentation from */
  326.     cptr = &curwp->w_dotp->l_text[0];
  327.  
  328.     /* check for a brace */
  329.     tptr = curwp->w_doto - 1;
  330.     bracef = (cptr[tptr] == '{');
  331.  
  332.     /* save the indent of the previous line */
  333.     i = 0;
  334.     while ((i < tptr) && (cptr[i] == ' ' || cptr[i] == '\t')
  335.         && (i < NSTRING - 1)) {
  336.         ichar[i] = cptr[i];
  337.         ++i;
  338.     }
  339.     ichar[i] = 0;        /* terminate it */
  340.  
  341.     /* put in the newline */
  342.     if (lnewline() == FALSE)
  343.         return(FALSE);
  344.  
  345.     /* and the saved indentation */
  346.     i = 0;
  347.     while (ichar[i])
  348.         linsert(1, ichar[i++]);
  349.  
  350.     /* and one more tab for a brace */
  351.     if (bracef)
  352.         tab(FALSE, 1);
  353.  
  354.     return(TRUE);
  355. }
  356.  
  357. insbrace(n, c)    /* insert a brace into the text here...we are in CMODE */
  358.  
  359. int n;    /* repeat count */
  360. int c;    /* brace to insert (always { for now) */
  361.  
  362. {
  363.     register int ch;    /* last character before input */
  364.     register int i;
  365.     register int target;    /* column brace should go after */
  366.  
  367.     /* if we are at the beginning of the line, no go */
  368.     if (curwp->w_doto == 0)
  369.         return(linsert(n,c));
  370.         
  371.     /* scan to see if all space before this is white space */
  372.     for (i = curwp->w_doto - 1; i >= 0; --i) {
  373.         ch = lgetc(curwp->w_dotp, i);
  374.         if (ch != ' ' && ch != '\t')
  375.             return(linsert(n, c));
  376.     }
  377.  
  378.     /* delete back first */
  379.     target = getccol(FALSE);    /* calc where we will delete to */
  380.     target -= 1;
  381.     target -= target % (tabsize == 0 ? 8 : tabsize);
  382.     while (getccol(FALSE) > target)
  383.         backdel(FALSE, 1);
  384.  
  385.     /* and insert the required brace(s) */
  386.     return(linsert(n, c));
  387. }
  388.  
  389. inspound()    /* insert a # into the text here...we are in CMODE */
  390.  
  391. {
  392.     register int ch;    /* last character before input */
  393.     register int i;
  394.  
  395.     /* if we are at the beginning of the line, no go */
  396.     if (curwp->w_doto == 0)
  397.         return(linsert(1,'#'));
  398.         
  399.     /* scan to see if all space before this is white space */
  400.     for (i = curwp->w_doto - 1; i >= 0; --i) {
  401.         ch = lgetc(curwp->w_dotp, i);
  402.         if (ch != ' ' && ch != '\t')
  403.             return(linsert(1, '#'));
  404.     }
  405.  
  406.     /* delete back first */
  407.     while (getccol(FALSE) >= 1)
  408.         backdel(FALSE, 1);
  409.  
  410.     /* and insert the required pound */
  411.     return(linsert(1, '#'));
  412. }
  413.  
  414. /*
  415.  * Delete blank lines around dot. What this command does depends if dot is
  416.  * sitting on a blank line. If dot is sitting on a blank line, this command
  417.  * deletes all the blank lines above and below the current line. If it is
  418.  * sitting on a non blank line then it deletes all of the blank lines after
  419.  * the line. Normally this command is bound to "C-X C-O". Any argument is
  420.  * ignored.
  421.  */
  422. deblank(f, n)
  423. {
  424.         register LINE   *lp1;
  425.         register LINE   *lp2;
  426.         long nld;
  427.  
  428.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  429.         return(rdonly());    /* we are in read only mode    */
  430.         lp1 = curwp->w_dotp;
  431.         while (llength(lp1)==0 && (lp2=lback(lp1))!=curbp->b_linep)
  432.                 lp1 = lp2;
  433.         lp2 = lp1;
  434.         nld = 0;
  435.         while ((lp2=lforw(lp2))!=curbp->b_linep && llength(lp2)==0)
  436.                 ++nld;
  437.         if (nld == 0)
  438.                 return (TRUE);
  439.         curwp->w_dotp = lforw(lp1);
  440.         curwp->w_doto = 0;
  441.         return (ldelete(nld, FALSE));
  442. }
  443.  
  444. /*
  445.  * Insert a newline, then enough tabs and spaces to duplicate the indentation
  446.  * of the previous line. Assumes tabs are every eight characters. Quite simple.
  447.  * Figure out the indentation of the current line. Insert a newline by calling
  448.  * the standard routine. Insert the indentation by inserting the right number
  449.  * of tabs and spaces. Return TRUE if all ok. Return FALSE if one of the
  450.  * subcomands failed. Normally bound to "C-J".
  451.  */
  452. indent(f, n)
  453. {
  454.         register int    nicol;
  455.         register int    c;
  456.         register int    i;
  457.  
  458.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  459.         return(rdonly());    /* we are in read only mode    */
  460.         if (n < 0)
  461.                 return (FALSE);
  462.         while (n--) {
  463.                 nicol = 0;
  464.                 for (i=0; i<llength(curwp->w_dotp); ++i) {
  465.                         c = lgetc(curwp->w_dotp, i);
  466.                         if (c!=' ' && c!='\t')
  467.                                 break;
  468.                         if (c == '\t')
  469.                                 nicol |= 0x07;
  470.                         ++nicol;
  471.                 }
  472.                 if (lnewline() == FALSE
  473.                 || ((i=nicol/8)!=0 && linsert(i, '\t')==FALSE)
  474.                 || ((i=nicol%8)!=0 && linsert(i,  ' ')==FALSE))
  475.                         return (FALSE);
  476.         }
  477.         return (TRUE);
  478. }
  479.  
  480. /*
  481.  * Delete forward. This is real easy, because the basic delete routine does
  482.  * all of the work. Watches for negative arguments, and does the right thing.
  483.  * If any argument is present, it kills rather than deletes, to prevent loss
  484.  * of text if typed with a big argument. Normally bound to "C-D".
  485.  */
  486. forwdel(f, n)
  487. {
  488.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  489.         return(rdonly());    /* we are in read only mode    */
  490.         if (n < 0)
  491.                 return (backdel(f, -n));
  492.         if (f != FALSE) {                       /* Really a kill.       */
  493.                 if ((lastflag&CFKILL) == 0)
  494.                         kdelete();
  495.                 thisflag |= CFKILL;
  496.         }
  497.         return (ldelete((long)n, f));
  498. }
  499.  
  500. /*
  501.  * Delete backwards. This is quite easy too, because it's all done with other
  502.  * functions. Just move the cursor back, and delete forwards. Like delete
  503.  * forward, this actually does a kill if presented with an argument. Bound to
  504.  * both "RUBOUT" and "C-H".
  505.  */
  506. backdel(f, n)
  507. {
  508.         register int    s;
  509.  
  510.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  511.         return(rdonly());    /* we are in read only mode    */
  512.         if (n < 0)
  513.                 return (forwdel(f, -n));
  514.         if (f != FALSE) {                       /* Really a kill.       */
  515.                 if ((lastflag&CFKILL) == 0)
  516.                         kdelete();
  517.                 thisflag |= CFKILL;
  518.         }
  519.         if ((s=backchar(f, n)) == TRUE)
  520.                 s = ldelete((long)n, f);
  521.         return (s);
  522. }
  523.  
  524. /*
  525.  * Kill text. If called without an argument, it kills from dot to the end of
  526.  * the line, unless it is at the end of the line, when it kills the newline.
  527.  * If called with an argument of 0, it kills from the start of the line to dot.
  528.  * If called with a positive argument, it kills from dot forward over that
  529.  * number of newlines. If called with a negative argument it kills backwards
  530.  * that number of newlines. Normally bound to "C-K".
  531.  */
  532. killtext(f, n)
  533. {
  534.         register LINE   *nextp;
  535.         long chunk;
  536.  
  537.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  538.         return(rdonly());    /* we are in read only mode    */
  539.         if ((lastflag&CFKILL) == 0)             /* Clear kill buffer if */
  540.                 kdelete();                      /* last wasn't a kill.  */
  541.         thisflag |= CFKILL;
  542.         if (f == FALSE) {
  543.                 chunk = llength(curwp->w_dotp)-curwp->w_doto;
  544.                 if (chunk == 0)
  545.                         chunk = 1;
  546.         } else if (n == 0) {
  547.                 chunk = curwp->w_doto;
  548.                 curwp->w_doto = 0;
  549.         } else if (n > 0) {
  550.                 chunk = llength(curwp->w_dotp)-curwp->w_doto+1;
  551.                 nextp = lforw(curwp->w_dotp);
  552.                 while (--n) {
  553.                         if (nextp == curbp->b_linep)
  554.                                 return (FALSE);
  555.                         chunk += llength(nextp)+1;
  556.                         nextp = lforw(nextp);
  557.                 }
  558.         } else {
  559.                 mlwrite("neg kill");
  560.                 return (FALSE);
  561.         }
  562.         return(ldelete(chunk, TRUE));
  563. }
  564.  
  565. setmode(f, n)    /* prompt and set an editor mode */
  566.  
  567. int f, n;    /* default and argument */
  568.  
  569. {
  570.     adjustmode(TRUE, FALSE);
  571. }
  572.  
  573. delmode(f, n)    /* prompt and delete an editor mode */
  574.  
  575. int f, n;    /* default and argument */
  576.  
  577. {
  578.     adjustmode(FALSE, FALSE);
  579. }
  580.  
  581. setgmode(f, n)    /* prompt and set a global editor mode */
  582.  
  583. int f, n;    /* default and argument */
  584.  
  585. {
  586.     adjustmode(TRUE, TRUE);
  587. }
  588.  
  589. delgmode(f, n)    /* prompt and delete a global editor mode */
  590.  
  591. int f, n;    /* default and argument */
  592.  
  593. {
  594.     adjustmode(FALSE, TRUE);
  595. }
  596.  
  597. adjustmode(kind, global)    /* change the editor mode status */
  598.  
  599. int kind;    /* true = set,        false = delete */
  600. int global;    /* true = global flag,    false = current buffer flag */
  601. {
  602.     register char *scan;        /* scanning pointer to convert prompt */
  603.     register int i;            /* loop index */
  604.     register status;        /* error return on input */
  605. #if    COLOR
  606.     register int uflag;        /* was modename uppercase?    */
  607. #endif
  608.     char prompt[50];    /* string to prompt user with */
  609.     char cbuf[NPAT];        /* buffer to recieve mode name into */
  610.  
  611.     /* build the proper prompt string */
  612.     if (global)
  613.         strcpy(prompt,"Global mode to ");
  614.     else
  615.         strcpy(prompt,"Mode to ");
  616.  
  617.     if (kind == TRUE)
  618.         strcat(prompt, "add: ");
  619.     else
  620.         strcat(prompt, "delete: ");
  621.  
  622.     /* prompt the user and get an answer */
  623.  
  624.     status = mlreply(prompt, cbuf, NPAT - 1);
  625.     if (status != TRUE)
  626.         return(status);
  627.  
  628.     /* make it uppercase */
  629.  
  630.     scan = cbuf;
  631. #if    COLOR
  632.     uflag = (*scan >= 'A' && *scan <= 'Z');
  633. #endif
  634.     while (*scan != 0) {
  635.         if (*scan >= 'a' && *scan <= 'z')
  636.             *scan = *scan - 32;
  637.         scan++;
  638.     }
  639.  
  640.     /* test it first against the colors we know */
  641.     for (i=0; i<NCOLORS; i++) {
  642.         if (strcmp(cbuf, cname[i]) == 0) {
  643.             /* finding the match, we set the color */
  644. #if    COLOR
  645.             if (uflag)
  646.                 if (global)
  647.                     gfcolor = i;
  648.                 else
  649.                     curwp->w_fcolor = i;
  650.             else
  651.                 if (global)
  652.                     gbcolor = i;
  653.                 else
  654.                     curwp->w_bcolor = i;
  655.  
  656.             curwp->w_flag |= WFCOLR;
  657. #endif
  658.             mlerase();
  659.             return(TRUE);
  660.         }
  661.     }
  662.  
  663.     /* test it against the modes we know */
  664.  
  665.     for (i=0; i < NUMMODES; i++) {
  666.         if (strcmp(cbuf, modename[i]) == 0) {
  667.             /* finding a match, we process it */
  668.             if (kind == TRUE)
  669.                 if (global)
  670.                     gmode |= (1 << i);
  671.                 else
  672.                     curwp->w_bufp->b_mode |= (1 << i);
  673.             else
  674.                 if (global)
  675.                     gmode &= ~(1 << i);
  676.                 else
  677.                     curwp->w_bufp->b_mode &= ~(1 << i);
  678.             /* display new mode line */
  679.             if (global == 0)
  680.                 upmode();
  681.             mlerase();    /* erase the junk */
  682.             return(TRUE);
  683.         }
  684.     }
  685.  
  686.     mlwrite("No such mode!");
  687.     return(FALSE);
  688. }
  689.  
  690. /*    This function simply clears the message line,
  691.         mainly for macro usage            */
  692.  
  693. clrmes(f, n)
  694.  
  695. int f, n;    /* arguments ignored */
  696.  
  697. {
  698.     mlwrite("");
  699.     return(TRUE);
  700. }
  701.  
  702. /*    This function writes a string on the message line
  703.         mainly for macro usage            */
  704.  
  705. writemsg(f, n)
  706.  
  707. int f, n;    /* arguments ignored */
  708.  
  709. {
  710.     register char *sp;    /* pointer into buf to expand %s */
  711.     register char *np;    /* ptr into nbuf */
  712.     register int status;
  713.     char buf[NPAT];        /* buffer to recieve message into */
  714.     char nbuf[NPAT*2];    /* buffer to expand string into */
  715.  
  716.     if ((status = mlreply("Message to write: ", buf, NPAT - 1)) != TRUE)
  717.         return(status);
  718.  
  719.     /* expand all '%' to "%%" so mlwrite won't expect arguments */
  720.     sp = buf;
  721.     np = nbuf;
  722.     while (*sp) {
  723.         *np++ = *sp;
  724.         if (*sp++ == '%')
  725.             *np++ = '%';
  726.     }
  727.     *np = '\0';
  728.     mlwrite(nbuf);
  729.     return(TRUE);
  730. }
  731.  
  732. #if    CFENCE
  733. /*    the cursor is moved to a matching fence    */
  734.  
  735. getfence(f, n)
  736.  
  737. int f, n;    /* not used */
  738.  
  739. {
  740.     register LINE *oldlp;    /* original line pointer */
  741.     register int oldoff;    /* and offset */
  742.     register int sdir;    /* direction of search (1/-1) */
  743.     register int count;    /* current fence level count */
  744.     register char ch;    /* fence type to match against */
  745.     register char ofence;    /* open fence */
  746.     register char c;    /* current character in scan */
  747.  
  748.     /* save the original cursor position */
  749.     oldlp = curwp->w_dotp;
  750.     oldoff = curwp->w_doto;
  751.  
  752.     /* get the current character */
  753.     if (oldoff == llength(oldlp))
  754.         ch = '\n';
  755.     else
  756.         ch = lgetc(oldlp, oldoff);
  757.  
  758.     /* setup proper matching fence */
  759.     switch (ch) {
  760.         case '(': ofence = ')'; sdir = FORWARD; break;
  761.         case '{': ofence = '}'; sdir = FORWARD; break;
  762.         case '[': ofence = ']'; sdir = FORWARD; break;
  763.         case ')': ofence = '('; sdir = REVERSE; break;
  764.         case '}': ofence = '{'; sdir = REVERSE; break;
  765.         case ']': ofence = '['; sdir = REVERSE; break;
  766.         default: TTbeep(); return(FALSE);
  767.     }
  768.  
  769.     /* set up for scan */
  770.     count = 1;
  771.     if (sdir == REVERSE)
  772.         backchar(FALSE, 1);
  773.     else
  774.         forwchar(FALSE, 1);
  775.  
  776.     /* scan until we find it, or reach the end of file */
  777.     while (count > 0) {
  778.         if (curwp->w_doto == llength(curwp->w_dotp))
  779.             c = '\n';
  780.         else
  781.             c = lgetc(curwp->w_dotp, curwp->w_doto);
  782.         if (c == ch)
  783.             ++count;
  784.         if (c == ofence)
  785.             --count;
  786.         if (sdir == FORWARD)
  787.             forwchar(FALSE, 1);
  788.         else
  789.             backchar(FALSE, 1);
  790.         if (boundry(curwp->w_dotp, curwp->w_doto, sdir))
  791.             break;
  792.     }
  793.  
  794.     /* if count is zero, we have a match, move the sucker */
  795.     if (count == 0) {
  796.         if (sdir == FORWARD)
  797.             backchar(FALSE, 1);
  798.         else
  799.             forwchar(FALSE, 1);
  800.         curwp->w_flag |= WFMOVE;
  801.         return(TRUE);
  802.     }
  803.  
  804.     /* restore the current position */
  805.     curwp->w_dotp = oldlp;
  806.     curwp->w_doto = oldoff;
  807.     TTbeep();
  808.     return(FALSE);
  809. }
  810. #endif
  811.  
  812. /*    Close fences are matched against their partners, and if
  813.     on screen the cursor briefly lights there        */
  814.  
  815. fmatch(ch)
  816.  
  817. char ch;    /* fence type to match against */
  818.  
  819. {
  820.     register LINE *oldlp;    /* original line pointer */
  821.     register int oldoff;    /* and offset */
  822.     register LINE *toplp;    /* top line in current window */
  823.     register int count;    /* current fence level count */
  824.     register char opench;    /* open fence */
  825.     register char c;    /* current character in scan */
  826.     register int i;
  827.  
  828.     /* first get the display update out there */
  829.     update(FALSE);
  830.  
  831.     /* save the original cursor position */
  832.     oldlp = curwp->w_dotp;
  833.     oldoff = curwp->w_doto;
  834.  
  835.     /* setup proper open fence for passed close fence */
  836.     if (ch == ')')
  837.         opench = '(';
  838.     else if (ch == '}')
  839.         opench = '{';
  840.     else
  841.         opench = '[';
  842.  
  843.     /* find the top line and set up for scan */
  844.     toplp = curwp->w_linep->l_bp;
  845.     count = 1;
  846.     backchar(FALSE, 2);
  847.  
  848.     /* scan back until we find it, or reach past the top of the window */
  849.     while (count > 0 && curwp->w_dotp != toplp) {
  850.         if (curwp->w_doto == llength(curwp->w_dotp))
  851.             c = '\n';
  852.         else
  853.             c = lgetc(curwp->w_dotp, curwp->w_doto);
  854.         if (c == ch)
  855.             ++count;
  856.         if (c == opench)
  857.             --count;
  858.         backchar(FALSE, 1);
  859.         if (curwp->w_dotp == curwp->w_bufp->b_linep->l_fp &&
  860.             curwp->w_doto == 0)
  861.             break;
  862.     }
  863.  
  864.     /* if count is zero, we have a match, display the sucker */
  865.     /* there is a real machine dependant timing problem here we have
  866.        yet to solve......... */
  867.     if (count == 0) {
  868.         forwchar(FALSE, 1);
  869.         for (i = 0; i < term.t_pause; i++)
  870.             update(FALSE);
  871.     }
  872.  
  873.     /* restore the current position */
  874.     curwp->w_dotp = oldlp;
  875.     curwp->w_doto = oldoff;
  876.     return(TRUE);
  877. }
  878.  
  879. istring(f, n)    /* ask for and insert a string into the current
  880.            buffer at the current point */
  881.  
  882. int f, n;    /* ignored arguments */
  883.  
  884. {
  885.     register char *tp;    /* pointer into string to add */
  886.     register int status;    /* status return code */
  887.     char tstring[NPAT+1];    /* string to add */
  888.  
  889.     /* ask for string to insert */
  890.     status = mlreplyt("String to insert<META>: ", tstring, NPAT, metac);
  891.     if (status != TRUE)
  892.         return(status);
  893.  
  894.     if (f == FALSE)
  895.         n = 1;
  896.  
  897.     if (n < 0)
  898.         n = - n;
  899.  
  900.     /* insert it */
  901.     while (n--) {
  902.         tp = &tstring[0];
  903.         while (*tp) {
  904.             if (*tp == 0x0a)
  905.                 status = lnewline();
  906.             else
  907.                 status = linsert(1, *tp);
  908.             ++tp;
  909.             if (status != TRUE)
  910.                 return(status);
  911.         }
  912.     }
  913.         
  914.     return(TRUE);
  915. }
  916.  
  917.